package com.cmeduSystem.webadmin.app.controller;

import cn.dev33.satoken.annotation.SaCheckPermission;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.core.util.ObjectUtil;
import com.cmeduSystem.common.flow.base.service.BaseFlowService;
import com.cmeduSystem.common.flow.constant.FlowTaskStatus;
import com.cmeduSystem.common.flow.constant.FlowConstant;
import com.cmeduSystem.common.flow.dto.FlowTaskCommentDto;
import com.cmeduSystem.common.flow.dto.FlowWorkOrderDto;
import com.cmeduSystem.common.flow.model.FlowEntry;
import com.cmeduSystem.common.flow.model.FlowEntryPublish;
import com.cmeduSystem.common.flow.model.FlowTaskComment;
import com.cmeduSystem.common.flow.model.FlowWorkOrder;
import com.cmeduSystem.common.flow.object.FlowRuntimeObject;
import com.cmeduSystem.common.flow.service.FlowApiService;
import com.cmeduSystem.common.flow.service.FlowWorkOrderService;
import com.cmeduSystem.common.flow.util.FlowCustomExtFactory;
import com.cmeduSystem.common.flow.util.FlowOperationHelper;
import com.cmeduSystem.common.flow.vo.*;
import com.cmeduSystem.common.core.annotation.DisableDataFilter;
import com.cmeduSystem.common.log.annotation.OperationLog;
import com.cmeduSystem.common.log.model.constant.SysOperationLogType;
import com.cmeduSystem.webadmin.upms.model.SysUser;
import com.cmeduSystem.webadmin.upms.service.SysUserService;
import com.github.pagehelper.page.PageMethod;
import com.cmeduSystem.webadmin.app.vo.*;
import com.cmeduSystem.webadmin.app.dto.*;
import com.cmeduSystem.webadmin.app.model.*;
import com.cmeduSystem.webadmin.app.service.*;
import com.cmeduSystem.common.core.object.*;
import com.cmeduSystem.common.core.util.*;
import com.cmeduSystem.common.core.constant.*;
import com.cmeduSystem.common.core.annotation.MyRequestBody;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import org.flowable.engine.history.HistoricProcessInstance;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.task.api.Task;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 工单信息操作控制器类。
 *
 * @author xulei
 * @date 2025-09-04
 */
@Tag(name = "工单信息管理接口")
@Slf4j
@RestController
@RequestMapping("/admin/app/ticketInfo")
public class TicketInfoController {

    @Autowired
    private FlowOperationHelper flowOperationHelper;
    @Autowired
    private FlowApiService flowApiService;
    @Autowired
    private FlowWorkOrderService flowWorkOrderService;
    @Autowired
    private FlowCustomExtFactory flowCustomExtFactory;
    @Autowired
    private TicketInfoService ticketInfoService;
    @Autowired
    private SysUserService sysUserService;



    /**
     * 新增工单信息数据。
     *
     * @param ticketInfoDto 新增对象。
     * @return 应答结果对象，包含新增对象主键Id。
     */
    @ApiOperationSupport(ignoreParameters = {"ticketInfoDto.id"})
    @SaCheckPermission("ticketInfo.add")
    @OperationLog(type = SysOperationLogType.ADD)
    @PostMapping("/add")
    public ResponseResult<Long> add(@MyRequestBody TicketInfoDto ticketInfoDto) {
        String errorMessage = MyCommonUtil.getModelValidationError(ticketInfoDto, false);
        if (errorMessage != null) {
            return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, errorMessage);
        }
        TicketInfo ticketInfo = MyModelUtil.copyTo(ticketInfoDto, TicketInfo.class);
        ticketInfo = ticketInfoService.saveNew(ticketInfo);
        return ResponseResult.success(ticketInfo.getId());
    }

    /**
     * 更新工单信息数据。
     *
     * @param ticketInfoDto 更新对象。
     * @return 应答结果对象。
     */
    @SaCheckPermission("ticketInfo.update")
    @OperationLog(type = SysOperationLogType.UPDATE)
    @PostMapping("/update")
    public ResponseResult<Void> update(@MyRequestBody TicketInfoDto ticketInfoDto) {
        String errorMessage = MyCommonUtil.getModelValidationError(ticketInfoDto, true);
        if (errorMessage != null) {
            return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, errorMessage);
        }
        TicketInfo ticketInfo = MyModelUtil.copyTo(ticketInfoDto, TicketInfo.class);
        TicketInfo originalTicketInfo = ticketInfoService.getById(ticketInfo.getId());
        if (originalTicketInfo == null) {
            // NOTE: 修改下面方括号中的话述
            errorMessage = "数据验证失败，当前 [数据] 并不存在，请刷新后重试！";
            return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST, errorMessage);
        }
        if (flowWorkOrderService.existByBusinessKey(
                ticketInfoService.getTableModelInfo().getTableName(), ticketInfoDto.getId(), true)) {
            return ResponseResult.error(ErrorCodeEnum.FLOW_WORK_ORDER_EXIST);
        }
        if (!ticketInfoService.update(ticketInfo, originalTicketInfo)) {
            return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST);
        }
        return ResponseResult.success();
    }

    /**
     * 删除工单信息数据。
     *
     * @param id 删除对象主键Id。
     * @return 应答结果对象。
     */
    @SaCheckPermission("ticketInfo.delete")
    @OperationLog(type = SysOperationLogType.DELETE)
    @PostMapping("/delete")
    public ResponseResult<Void> delete(@MyRequestBody Long id) {
        if (MyCommonUtil.existBlankArgument(id)) {
            return ResponseResult.error(ErrorCodeEnum.ARGUMENT_NULL_EXIST);
        }
        return this.doDelete(id);
    }

    /**
     * 批量删除工单信息数据。
     *
     * @param idList 待删除对象的主键Id列表。
     * @return 应答结果对象。
     */
    @SaCheckPermission("ticketInfo.delete")
    @OperationLog(type = SysOperationLogType.DELETE_BATCH)
    @PostMapping("/deleteBatch")
    public ResponseResult<Void> deleteBatch(@MyRequestBody List<Long> idList) {
        if (MyCommonUtil.existBlankArgument(idList)) {
            return ResponseResult.error(ErrorCodeEnum.ARGUMENT_NULL_EXIST);
        }
        for (Long id : idList) {
            ResponseResult<Void> responseResult = this.doDelete(id);
            if (!responseResult.isSuccess()) {
                return responseResult;
            }
        }
        return ResponseResult.success();
    }

    /**
     * 根据指定流程的主版本，发起一个流程实例。该操作将携带业务主表的主键数据Id。
     *
     * @param processDefinitionKey 流程标识。
     * @param id 流程实例关联的业务主键Id。
     * @param taskVariableData 流程任务变量数据。
     * @return 应答结果对象。
     */
    @DisableDataFilter
    @SaCheckPermission("ticketInfo.workflow.ggFlow")
    @OperationLog(type = SysOperationLogType.START_FLOW)
    @PostMapping("/startWithBusinessKey/{processDefinitionKey}")
    public ResponseResult<Void> startWithBusinessKey(
            @PathVariable("processDefinitionKey") String processDefinitionKey,
            @MyRequestBody(required = true) Long id,
            @MyRequestBody JSONObject taskVariableData) {
        ResponseResult<FlowEntryPublish> result =
                flowOperationHelper.verifyAndGetFlowEntryPublish(processDefinitionKey);
        if (!result.isSuccess()) {
            return ResponseResult.errorFrom(result);
        }
        FlowEntryPublish flowEntryPublish = result.getData();
        if (!ticketInfoService.existId(id)) {
            return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST);
        }
        if (flowWorkOrderService.existByBusinessKey(
                ticketInfoService.getTableModelInfo().getTableName(), id, true)) {
            return ResponseResult.error(ErrorCodeEnum.FLOW_WORK_ORDER_EXIST);
        }
        ticketInfoService.startWithBusinessKey(
                flowEntryPublish.getProcessDefinitionId(), id, taskVariableData);
        return ResponseResult.success();
    }

    /**
     * 根据指定流程的主版本，发起一个流程实例，同时作为第一个任务节点的执行人，执行第一个用户任务。
     *
     * @param processDefinitionKey 流程定义标识。
     * @param flowTaskCommentDto   审批意见。
     * @param taskVariableData     流程任务变量数据。
     * @param ticketInfoDto    新增对象。
     * @param copyData 传阅数据，格式为type和id，type的值参考FlowConstant中的常量值。
     * @return 应答结果对象。
     */
    @ApiOperationSupport(ignoreParameters = {"ticketInfoDto.id"})
    @DisableDataFilter
    @SaCheckPermission("ticketInfo.workflow.ggFlow")
    @OperationLog(type = SysOperationLogType.START_FLOW)
    @PostMapping("/startAndTakeUserTask/{processDefinitionKey}")
    public ResponseResult<Void> startAndTakeUserTask(
            @PathVariable("processDefinitionKey") String processDefinitionKey,
            @MyRequestBody(required = true) FlowTaskCommentDto flowTaskCommentDto,
            @MyRequestBody JSONObject taskVariableData,
            @MyRequestBody(required = true) TicketInfoDto ticketInfoDto,
            @MyRequestBody JSONObject copyData) {
        // 验证流程管理数据状态的合法性。
        ResponseResult<FlowEntry> flowEntryResult =
                flowOperationHelper.verifyFullAndGetFlowEntry(processDefinitionKey);
        if (!flowEntryResult.isSuccess()) {
            return ResponseResult.errorFrom(flowEntryResult);
        }
        String processDefinitionId = flowEntryResult.getData().getMainFlowEntryPublish().getProcessDefinitionId();
        FlowTaskComment flowTaskComment = MyModelUtil.copyTo(flowTaskCommentDto, FlowTaskComment.class);
        String errorMessage = MyCommonUtil.getModelValidationError(ticketInfoDto, false);
        if (errorMessage != null) {
            return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, errorMessage);
        }
        TicketInfo ticketInfo = MyModelUtil.copyTo(ticketInfoDto, TicketInfo.class);
        // 这里把传阅数据放到任务变量中，是为了避免给流程数据操作方法增加额外的方法调用参数。
        if (MapUtil.isNotEmpty(copyData)) {
            if (taskVariableData == null) {
                taskVariableData = new JSONObject();
            }
            taskVariableData.put(FlowConstant.COPY_DATA_KEY, copyData);
        }
        // 保存在线表单提交的数据，同时启动流程和自动完成第一个用户任务。
        ticketInfoService.saveNewAndStartProcess(
                processDefinitionId, flowTaskComment, taskVariableData, ticketInfo);
        return ResponseResult.success();
    }

    /**
     * 根据指定流程的主版本，发起一个流程实例，同时保存草稿数据。
     *
     * @param processDefinitionKey 流程定义标识。
     * @param processInstanceId    流程实例Id。
     * @param ticketInfoDto 主表对象。
     * @return 应答结果对象，草稿的待办任务对象。
     */
    @ApiOperationSupport(ignoreParameters = {"ticketInfoDto.id"})
    @DisableDataFilter
    @SaCheckPermission("ticketInfo.workflow.ggFlow")
    @OperationLog(type = SysOperationLogType.START_FLOW)
    @PostMapping("/startAndSaveDraft/{processDefinitionKey}")
    public ResponseResult<FlowTaskVo> startAndSaveDraft(
            @PathVariable("processDefinitionKey") String processDefinitionKey,
            @MyRequestBody String processInstanceId,
            @MyRequestBody TicketInfoDto ticketInfoDto) {
        String errorMessage;
        if (ObjectUtil.isEmpty(ticketInfoDto)) {
            errorMessage = "数据验证失败，业务数据不能全部为空！";
            return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, errorMessage);
        }
        ResponseResult<FlowEntry> flowEntryResult =
                flowOperationHelper.verifyFullAndGetFlowEntry(processDefinitionKey);
        if (!flowEntryResult.isSuccess()) {
            return ResponseResult.errorFrom(flowEntryResult);
        }
        TicketInfo ticketInfo = MyModelUtil.copyTo(ticketInfoDto, TicketInfo.class);
        ticketInfo.setCreateUserId(TokenData.takeFromRequest().getUserId());
        String masterData = JSON.toJSONString(ticketInfo);
        FlowWorkOrder flowWorkOrder;
        if (processInstanceId == null) {
            String processDefinitionId = flowEntryResult.getData().getMainFlowEntryPublish().getProcessDefinitionId();
            flowWorkOrder = ticketInfoService.saveNewDraftAndStartProcess(processDefinitionId, masterData, null);
        } else {
            ResponseResult<FlowWorkOrder> flowWorkOrderResult =
                    flowOperationHelper.verifyAndGetFlowWorkOrderWithDraft(processDefinitionKey, processInstanceId);
            if (!flowWorkOrderResult.isSuccess()) {
                return ResponseResult.errorFrom(flowEntryResult);
            }
            flowWorkOrder = flowWorkOrderResult.getData();
            ((BaseFlowService<?, ?>) ticketInfoService).updateDraft(flowWorkOrder.getWorkOrderId(), masterData, null);
        }
        List<FlowTaskVo> flowTaskVoList =
                flowApiService.getProcessInstanceActiveTaskListAndConvert(flowWorkOrder.getProcessInstanceId());
        return ResponseResult.success(flowTaskVoList.get(0));
    }

    /**
     * 提交流程的用户任务。
     *
     * @param processDefinitionKey 流程定义标识。
     * @param processInstanceId    流程实例Id。
     * @param taskId               流程任务Id。
     * @param flowTaskCommentDto   流程审批数据。
     * @param taskVariableData     流程任务变量数据。
     * @param delegateUserId       委托用户Id。
     * @param ticketInfoDto    新增对象。
     * @param copyData 传阅数据，格式为type和id，type的值参考FlowConstant中的常量值。
     * @return 应答结果对象。
     */
    @ApiOperationSupport(ignoreParameters = {"ticketInfoDto.id"})
    @DisableDataFilter
    @OperationLog(type = SysOperationLogType.SUBMIT_TASK)
    @PostMapping("/submitUserTask/{processDefinitionKey}")
    public ResponseResult<Void> submitUserTask(
            @PathVariable("processDefinitionKey") String processDefinitionKey,
            @MyRequestBody(required = true) String processInstanceId,
            @MyRequestBody(required = true) String taskId,
            @MyRequestBody(required = true) FlowTaskCommentDto flowTaskCommentDto,
            @MyRequestBody JSONObject taskVariableData,
            @MyRequestBody Long delegateUserId,
            @MyRequestBody TicketInfoDto ticketInfoDto,
            @MyRequestBody JSONObject copyData) {
        String errorMessage;
        ResponseResult<FlowRuntimeObject> result =
                flowOperationHelper.verifySubmitWithGetInstanceAndTask(
                        processInstanceId, taskId, flowTaskCommentDto, processDefinitionKey, delegateUserId);
        if (!result.isSuccess()) {
            return ResponseResult.errorFrom(result);
        }
        ProcessInstance instance = result.getData().getInstance();
        boolean forUpdate = StrUtil.isNotBlank(instance.getBusinessKey());
        // 流程业务输入数据验证和转换
        errorMessage = MyCommonUtil.getModelValidationError(ticketInfoDto, false);
        if (errorMessage != null) {
            return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, errorMessage);
        }
        TicketInfo ticketInfo = MyModelUtil.copyTo(ticketInfoDto, TicketInfo.class);
        // 这里把传阅数据放到任务变量中，是为了避免给流程数据操作方法增加额外的方法调用参数。
        if (MapUtil.isNotEmpty(copyData)) {
            if (taskVariableData == null) {
                taskVariableData = new JSONObject();
            }
            taskVariableData.put(FlowConstant.COPY_DATA_KEY, copyData);
        }
        FlowTaskComment flowTaskComment = MyModelUtil.copyTo(flowTaskCommentDto, FlowTaskComment.class);
        if (delegateUserId != null) {
            String delegateUsername = flowCustomExtFactory.getFlowIdentityExtHelper().mapLoginNameByUserId(delegateUserId);
            flowTaskComment.setDelegateUsername(delegateUsername);
        }
        if (!forUpdate) {
            ticketInfoService.saveNewAndTakeTask(
                    processInstanceId, taskId, flowTaskComment, taskVariableData, ticketInfo);
            return ResponseResult.success();
        }
        Long dataId = Long.valueOf(instance.getBusinessKey());
        TicketInfo originalTicketInfo = ticketInfoService.getById(dataId);
        if (originalTicketInfo == null) {
            errorMessage = "数据验证失败，原有业务数据不存在！";
            return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, errorMessage);
        }
        if (!ticketInfoService.updateAndTakeTask(result.getData().getTask(),
                flowTaskComment, taskVariableData, ticketInfo, originalTicketInfo)) {
            errorMessage = "数据更新失败，原有业务数据不存在！";
            return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, errorMessage);
        }
        return ResponseResult.success();
    }

    /**
     * 获取当前流程实例的详情数据。包括主表数据、一对一从表数据、一对多从表数据列表等。
     *
     * @param processDefinitionKey 流程定义标识。
     * @param processInstanceId    当前运行时的流程实例Id。
     * @param taskId               流程任务Id。
     * @param delegateUserId       委托用户Id。
     * @return 当前流程实例的详情数据。
     */
    @DisableDataFilter
    @GetMapping("/viewTaskBusinessData/{processDefinitionKey}")
    public ResponseResult<TicketInfoVo> viewTaskBusinessData(
            @PathVariable("processDefinitionKey") String processDefinitionKey,
            @RequestParam String processInstanceId,
            @RequestParam String taskId,
            @RequestParam(required = false) Long delegateUserId) {
        // 验证流程任务的合法性。
        Task task = flowApiService.getProcessInstanceActiveTask(processInstanceId, taskId);
        ResponseResult<TaskInfoVo> taskInfoResult = flowOperationHelper.verifyAndGetRuntimeTaskInfo(task, delegateUserId);
        if (!taskInfoResult.isSuccess()) {
            return ResponseResult.errorFrom(taskInfoResult);
        }
        ProcessInstance instance = flowApiService.getProcessInstance(processInstanceId);
        if (!StrUtil.equals(instance.getProcessDefinitionKey(), processDefinitionKey)) {
            String errorMessage = "数据验证失败，请求流程标识与流程实例不匹配，请核对！";
            return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, errorMessage);
        }
        Long dataId = Long.valueOf(instance.getBusinessKey());
        TicketInfo ticketInfo = ticketInfoService.getByIdWithRelation(dataId, MyRelationParam.full());
        if (ticketInfo == null) {
            return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST);
        }
        TicketInfoVo ticketInfoVo = MyModelUtil.copyTo(ticketInfo, TicketInfoVo.class);
        return ResponseResult.success(ticketInfoVo);
    }

    /**
     * 获取已经结束的流程实例的详情数据。包括主表数据、一对一从表数据、一对多从表数据列表等。
     *
     * @param processDefinitionKey 流程定义标识。
     * @param processInstanceId    历史流程实例Id。
     * @param taskId               历史任务Id。如果该值为null，仅有发起人可以查看当前流程数据，否则只有任务的指派人才能查看。
     * @return 历史流程实例的详情数据。
     */
    @DisableDataFilter
    @GetMapping("/viewHistoricTaskBusinessData/{processDefinitionKey}")
    public ResponseResult<TicketInfoVo> viewHistoricTaskBusinessData(
            @PathVariable("processDefinitionKey") String processDefinitionKey,
            @RequestParam String processInstanceId,
            @RequestParam(required = false) String taskId) {
        ResponseResult<HistoricProcessInstance> result = flowOperationHelper
                .verifyAndGetHistoricProcessInstance(processInstanceId, taskId, processDefinitionKey);
        if (!result.isSuccess()) {
            return ResponseResult.errorFrom(result);
        }
        String businessKey = result.getData().getBusinessKey();
        Long dataId = Long.valueOf(businessKey);
        TicketInfo ticketInfo = ticketInfoService.getByIdWithRelation(dataId, MyRelationParam.full());
        if (ticketInfo == null) {
            return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST);
        }

        TicketInfoVo ticketInfoVo = MyModelUtil.copyTo(ticketInfo, TicketInfoVo.class);
        return ResponseResult.success(ticketInfoVo);
    }

    /**
     * 工作流工单列表。
     *
     * @param processDefinitionKey   流程定义标识。
     * @param flowWorkOrderDtoFilter 过滤对象。
     * @param ticketInfoDtoFilter 业务表过滤对象。
     * @param orderParam             排序参数。
     * @param pageParam              分页参数。
     * @return 查询结果。
     */
    @SaCheckPermission("ticketInfo.workflow.ggFlow")
    @PostMapping("/listWorkOrder/{processDefinitionKey}")
    public ResponseResult<MyPageData<FlowWorkOrderVo>> listWorkOrder(
            @PathVariable("processDefinitionKey") String processDefinitionKey,
            @MyRequestBody FlowWorkOrderDto flowWorkOrderDtoFilter,
            @MyRequestBody TicketInfoDto ticketInfoDtoFilter,
            @MyRequestBody MyOrderParam orderParam,
            @MyRequestBody(required = true) MyPageParam pageParam) {
        List<String> businessKeys = null;
        if (ticketInfoDtoFilter != null && MyCommonUtil.hasNonEmptyFields(ticketInfoDtoFilter)) {
            TicketInfo filter = MyModelUtil.copyTo(ticketInfoDtoFilter, TicketInfo.class);
            List<TicketInfo> dataList = ticketInfoService.getTicketInfoList(filter, null);
            if (CollUtil.isEmpty(dataList)) {
                return ResponseResult.success(MyPageData.emptyPageData());
            }
            businessKeys = dataList.stream()
                    .map(data -> data.getId().toString()).collect(Collectors.toList());
        }
        MyPageData<FlowWorkOrderVo> resultData = flowWorkOrderService
                .getPagedWorkOrderListAndBuildData(processDefinitionKey, flowWorkOrderDtoFilter, businessKeys, pageParam, orderParam);
        // 工单自身的查询中可以受到数据权限的过滤，但是工单集成业务数据时，则无需再对业务数据进行数据权限过滤了。
        GlobalThreadLocal.setDataFilter(false);
        // 获取非草稿工单中的流程实例businessKey，并作为主键Id集合去关联主表中的数据，主表会自动关联从表数据的。
        Set<String> businessKeySet = resultData.getDataList().stream()
                .map(FlowWorkOrderVo::getBusinessKey)
                .filter(Objects::nonNull).collect(Collectors.toSet());
        if (CollUtil.isNotEmpty(businessKeySet)) {
            // 根据主键Id类型进行转换。
            Set<Long> convertedBusinessKeySet = businessKeySet.stream().map(Long::valueOf).collect(Collectors.toSet());
            // 通过in list的方式批量查询主表及其关联从表的数据。
            List<TicketInfo> ticketInfoList =
                    ticketInfoService.getInListWithRelation(convertedBusinessKeySet, MyRelationParam.normal());
            // 将业务数据与工单数据绑定，之后再返回给前端。
            flowOperationHelper.buildWorkOrderBusinessData(
                    resultData.getDataList(), ticketInfoList, TicketInfo::getId);
        }
        List<FlowWorkOrderVo> draftWorkOrderList = resultData.getDataList().stream()
                .filter(c -> c.getFlowStatus().equals(FlowTaskStatus.DRAFT)).collect(Collectors.toList());
        ((BaseFlowService<?, ?>) ticketInfoService).buildDraftData(draftWorkOrderList);
        return ResponseResult.success(resultData);
    }

    /**
     * 列出符合过滤条件的工单信息列表。
     *
     * @param ticketInfoDtoFilter 过滤对象。
     * @param orderParam 排序参数。
     * @param pageParam 分页参数。
     * @return 应答结果对象，包含查询结果集。
     */
    @SaCheckPermission("ticketInfo.view")
    @PostMapping("/list")
    public ResponseResult<MyPageData<TicketInfoVo>> list(
            @MyRequestBody TicketInfoDto ticketInfoDtoFilter,
            @MyRequestBody MyOrderParam orderParam,
            @MyRequestBody MyPageParam pageParam) {
        if (pageParam != null) {
            PageMethod.startPage(pageParam.getPageNum(), pageParam.getPageSize(), pageParam.getCount());
        }
        TicketInfo ticketInfoFilter = MyModelUtil.copyTo(ticketInfoDtoFilter, TicketInfo.class);
        String orderBy = MyOrderParam.buildOrderBy(orderParam, TicketInfo.class);
        List<TicketInfo> ticketInfoList = ticketInfoService.getTicketInfoListWithRelation(ticketInfoFilter, orderBy);
        return ResponseResult.success(MyPageUtil.makeResponseData(ticketInfoList, TicketInfoVo.class));
    }

    /**
     * 查看指定工单信息对象详情。
     *
     * @param id 指定对象主键Id。
     * @return 应答结果对象，包含对象详情。
     */
    @SaCheckPermission("ticketInfo.view")
    @GetMapping("/view")
    public ResponseResult<TicketInfoVo> view(@RequestParam Long id) {
        TicketInfo ticketInfo = ticketInfoService.getByIdWithRelation(id, MyRelationParam.full());
        if (ticketInfo == null) {
            return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST);
        }
        TicketInfoVo ticketInfoVo = MyModelUtil.copyTo(ticketInfo, TicketInfoVo.class);
        return ResponseResult.success(ticketInfoVo);
    }

    private ResponseResult<Void> doDelete(Long id) {
        String errorMessage;
        // 验证关联Id的数据合法性
        TicketInfo originalTicketInfo = ticketInfoService.getById(id);
        if (originalTicketInfo == null) {
            // NOTE: 修改下面方括号中的话述
            errorMessage = "数据验证失败，当前 [对象] 并不存在，请刷新后重试！";
            return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST, errorMessage);
        }
        if (flowWorkOrderService.existByBusinessKey(
                ticketInfoService.getTableModelInfo().getTableName(), id, true)) {
            return ResponseResult.error(ErrorCodeEnum.FLOW_WORK_ORDER_EXIST);
        }
        if (!ticketInfoService.remove(id)) {
            errorMessage = "数据操作失败，删除的对象不存在，请刷新后重试！";
            return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST, errorMessage);
        }
        return ResponseResult.success();
    }
}
